Passed
Push — master ( 0d8196...8a109f )
by Night
01:08
created

arrayFuncs.removeAndInsert   B

Complexity

Conditions 8
Paths 32

Size

Total Lines 44
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 25
nc 32
nop 2
dl 0
loc 44
rs 7.3333
c 0
b 0
f 0
1
/** global: UB */
2
3
/*! ARRAY UTILS */
4
5
var arrayFuncs = {
6
	
7
	indexOf: function(value){
8
		var list = this;
9
		if (list.length === 0) {
10
			return -1;
11
		}
12
		for (var a = 0, al = list.length;a<al;a++){
13
			if (list[a] == value){
14
				return a;
15
			}
16
		}
17
		return -1;
18
	},
19 View Code Duplication
	lastIndexOf: function(value){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
20
		var list = this;
21
		if (list.length === 0) {
22
			return -1;
23
		}
24
		for (var a = list.length-1;a>=0;a--){
25
			if (list[a] == value){
26
				return a;
27
			}
28
		}
29
		return -1;
30
	},
31
	isEqual: function(list2){
32
		var list = this;
33
		if (list == null || list2 == null) {
2 ignored issues
show
Best Practice introduced by
Comparing list to null using the == operator is not safe. Consider using === instead.
Loading history...
Best Practice introduced by
Comparing list2 to null using the == operator is not safe. Consider using === instead.
Loading history...
34
			return list == list2;
35
		}	
36
		if(list.length != list2.length){
37
			return false;
38
		}
39
		
40
		var len = list.length;
41
		
42
		for (var i = 0;i<len;i++){
43
			if(list[i] !== list2[i]){
44
				return false;
45
			}
46
		}
47
		
48
		return true;
49
	},
50
	isNotEqual: function(list2){
51
		var list = this;
52
		return !IsEqual(list, list2);
53
	},
54
55
	exists: function(){
56
		var list = this;
57
		return list != null && list.length > 0;
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the != operator is not safe. Consider using !== instead.
Loading history...
58
	},
59
	isFirst: function(value){
60
		var list = this;
61
		return list != null && list[0] == value;
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the != operator is not safe. Consider using !== instead.
Loading history...
62
	},
63
	isLast: function(value){
64
		var list = this;
65
		return list != null && list[list.length - 1] == value;
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the != operator is not safe. Consider using !== instead.
Loading history...
66
	},
67 View Code Duplication
	count: function(value, not = false){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
68
		var list = this;
69
		var total = 0;
70
		for (var a = 0, al = list.length;a<al;a++){
71
			if (not) {
72
				if (list[a] != value) {
73
					total++;
74
				}
75
			}else {
76
				if (list[a] == value) {
77
					total++;
78
				}
79
			}
80
		}
81
		return total;
82
	},
83
	or: function(list2){
84
		var list = this;
85
		if (Exists(list)) {
86
			return list;
87
		}
88
		return list2;
89
	},
90
	
91
	part: function(start, end){
92
		var list = this;
93
		
94
		// quickly exit if no items or no results possible
95
		if (list == null || list.length === 0 || start > end || start >= list.length) {
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the == operator is not safe. Consider using === instead.
Loading history...
96
			return [];
97
		}
98
		
99
		// just get the part we need
100
		return list.slice(start, end + 1);
101
	},
102
	
103
	swap: function(slot1, slot2){
104
		var list = this;
105
		var temp = list[slot2];
106
		list[slot2] = list[slot1];
107
		list[slot1] = temp;
108
	},
109
110
	add: function(item){
111
		var list = this;
112
		list.push(item);
113
		return list.length - 1;
114
	},
115
	addToStart: function(item){
116
		var list = this;
117
		list.unshift(item);
118
		return 0;
119
	},
120
	/** return false if item exists, true if item does not */
121
	addOnce: function(value){
122
		var list = this;
123
		
124
		// return false if item exists
125
		if (list.indexOf(value) > -1) {
126
			return false;
127
		}
128
		
129
		// add if not found
130
		list.push(value);
131
		return true;
132
	},
133
	
134
	addArray: function(toAdd, addAtSlot = -1, modifyMain = true){
135
		var list = this;
136
		
137
		if (toAdd != null && toAdd.length > 0) {
1 ignored issue
show
Best Practice introduced by
Comparing toAdd to null using the != operator is not safe. Consider using !== instead.
Loading history...
138
			if (!modifyMain) {
139
				list = list.concat(); /// shallow clone
140
			}
141
			
142
			// set length first so allocates memory (maybe?)
143
			var origLen = list.length;
144
			if (addAtSlot == -1){
145
				list.length += toAdd.length;
146
			}
147
			
148
			// set all slots
149
			var next = addAtSlot == -1 ? origLen : addAtSlot;
150
			for (var a = 0, al = toAdd.length;a<al;a++, next++){
151
				list[next] = toAdd[a];
152
			}
153
		}
154
		return list;
155
	},
156
	
157
	/** adds the given value many times */
158
	addManyTimes: function(val, times){
159
		var list = this;
160
		
161
		if (times <= 0) {
162
			return list;
163
		}
164
		
165
		var n = list.length;
166
		for (var t = 0;t<times;t++){
167
			list[n++] = val;
168
		}
169
		
170
		return list;
171
	},
172
	
173
	addRange: function(toAdd, startSlot, endSlot){
174
		var list = this;
175
		
176
		// exit if no work
177
		if (endSlot < startSlot) {
178
			return;
179
		}
180
		
181
		// per wanted slot of the `add` array
182
		startSlot = startSlot.limitToArray(toAdd);
183
		endSlot = endSlot.limitToArray(toAdd);
184
		for (var s = startSlot;s <= endSlot;s++){
185
			
186
			// add into `main` array
187
			list.push(toAdd[s]);
188
			
189
		}
190
	},
191
	
192
	/** returns final index of added item, or index of already existing item */
193
	findOrAdd: function(value){
194
		var list = this;
195
		
196
		// return index of item if exists
197
		var i = list.indexOf(value);
198
		if (i > -1) {
199
			return i;
200
		}
201
		
202
		// add if not found
203
		i = list.length;
204
		list[i] = value;
205
		return i;
206
	},
207
	
208
	insertOne: function(item, slot){
209
		var list = this;
210
		
211
		// adds one slot at the given point
212
		// modifies the main array
213
		
214
		list.splice(slot, 0, item);
215
	},
216
217
	/** if slot = -1 or outside the array, the item is added to the END of the array.
218
	 * Otherwise the item is added at the given slot. */
219
	insertOneOrAdd: function(item, slot){
220
		var list = this;
221
		
222
		// adds one slot at the given point
223
		// modifies the main array
224
		
225
		if (slot < 0 || slot >= list.length) {
226
			list.push(item);
227
			return list.length - 1;
228
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
229
			list.splice(slot, 0, item);
230
			return slot;
231
		}
232
	},
233
	insertArray: function(newItems, slot, returnNew = true){
234
		var list = this;
235
		
236
		// adds many slots at the given point
237
		// returns a new array
238
		if(returnNew){
239
			return list.slice(0, slot).concat(newItems).concat(list.slice(slot));
240
		}
241
		
242
		// adds many slots at the given point
243
		// modifies the main array
244
		for (var a = 0, al = newItems.length;a<al;a++){
245
			list.splice(slot++, 0, newItems[a]);
246
		}
247
		return list;
248
	},
249
	insertArrayAfter: function(newItems, after){
250
		var list = this;
251
		if (list.isLast(after)) {
252
			list.addArray(newItems);
253
		} else {
254
			var i = list.indexOf(after);
255
			list.insertArray(i + 1, newItems);
256
		}
257
	},
258
	
259
260
	removeAndInsert: function(from, to){
261
		var list = this;
262
		
263
		// ensure slots within array
264
		var al = list.length;
265
		from = from.limitTo(0, al - 1);
266
		to = to.limitTo(0, al - 1);
267
		if (to < from) {
268
			var i1 = to;
269
			var i2 = from;
270
		}else {
271
			var i1 = from;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i1 already seems to be declared on line 268. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
272
			var i2 = to;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i2 already seems to be declared on line 269. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
273
		}
274
		
275
		// fill unaffected header
276
		var result = [];
277
		if(i1 > 0){
278
			for (var a = 0;a<i1;a++){
279
				result[a] = list[a];
280
			}
281
		}
282
		
283
		// fill "to"
284
		result[to] = list[from];
285
		
286
		// fill between from and to
287
		if(to < from){
288
			for (a = to + 1; a <= from; a++) {
289
				result[a] = list[a - 1];
290
			}
291
		}else {
292
			for (a = from; a < to; a++) {
293
				result[a] = list[a + 1];
294
			}
295
		}
296
		
297
		// fill unaffected footer
298
		for (var a = i2 + 1;a<al;a++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable a already seems to be declared on line 278. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
299
			result[a] = list[a];
300
		}
301
		
302
		return result;
303
	},
304
	
305
	/** replace a range of items with a given array */
306
	replaceRange: function(replaceStartSlot, replaceEndSlot, newItems, returnNew = true){
307
		var list = this;
308
		
309
		
310
		// simply remove a single item
311
		if (replaceStartSlot == replaceEndSlot && newItems.length === 0) {
312
			if (returnNew) {
313
				list = list.concat();
314
			}
315
			list.splice(replaceStartSlot, 1);
316
			return list;
317
			
318
		// simply replace a single item
319
		}else if (replaceStartSlot == replaceEndSlot && newItems.length == 1) {
1 ignored issue
show
Best Practice introduced by
Comparing newItems.length to 1 using the == operator is not safe. Consider using === instead.
Loading history...
320
			if (returnNew) {
321
				list = list.concat();
322
			}
323
			list[replaceStartSlot] = newItems[0];
324
			return list;
325
			
326
		}else{
327
			
328
			// alt method if returning a new array
329
			if(returnNew){
330
				return list.slice(0, replaceStartSlot).concat(newItems).concat(list.slice(replaceEndSlot + 1));
331
			}
332
			
333
			// remove many
334
			list.splice(replaceStartSlot, (replaceEndSlot - replaceStartSlot) + 1);
335
			
336
			// insert many
337
			var slot = replaceStartSlot;
338
			for (var a = 0, al = newItems.length;a<al;a++){
339
				list.splice(slot++, 0, newItems[a]);
340
			}
341
		}
342
		return list;
343
	},
344
	
345
	replace: function(find, replace, stringReplace = false){
346
		var list = this;
347
		for (var i = 0, il = list.length;i<il;i++){
348
			if (stringReplace){
349
350
				// replace substring within string items
351
				var str = list[i];
352
				if (str && str.constructor === String) {
353
					list[i] = str.replaceAll(find, replace);
354
				}
355
			}else{
356
357
				// replace entire items
358
				if (list[i] == find) {
359
					list[i] = replace;
360
				}
361
			}
362
		}
363
	},
364
	replaceOnce: function(find, replace){
365
		var list = this;
366
		for (var i = 0, il = list.length;i<il;i++){
367
			if (list[i] == find) {
368
				list[i] = replace;
369
				return;
370
			}
371
		}
372
	},
373
	replaceMany: function(findArray, replaceArray){
374
		var list = this;
375
		if (findArray.length != replaceArray.length){
376
			return;
377
		}
378
		for (var i = 0, il = list.length;i<il;i++){
379
			for (var f = 0, fl = findArray.length;f<fl;f++){
380
				var find = findArray[f];
381
				if (list[i] == find) {
382
					list[i] = replaceArray[f];
383
					break;
384
				}
385
			}
386
		}
387
	},
388
	
389
	
390
	remove: function(value, stringReplace = false){
391
		var list = this;
392
		for (var i = 0, il = list.length;i<il;i++){
393
			if (stringReplace){
394
395
				// remove substring within string items
396
				var str = list[i];
397
				if (str && str.constructor === String) {
398
					list[i] = str.removeAll(find);
0 ignored issues
show
Bug introduced by
The variable find seems to be never declared. If this is a global, consider adding a /** global: find */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
399
				}
400
			}else{
401
402
				// remove entire items
403
				if (list[i] == value) {
404
					list.splice(i, 1);
405
					i--;
1 ignored issue
show
Complexity Coding Style introduced by
You seem to be assigning a new value to the loop variable i here. Please check if this was indeed your intention. Even if it was, consider using another kind of loop instead.
Loading history...
406
					il--;
407
				}
408
			}
409
		}
410
	},
411
	removeOnce: function(val){
412
		var list = this;
413
		var i = list.indexOf(val);
414
		if (i > -1) {
415
			list.splice(i, 1);
416
		}
417
		return i;
418
	},
419
	removeFirst: function(returnNew = false){
420
		var list = this;
421
		if (returnNew) {
422
			return list.slice(1);
423
		}else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
424
			if (list.length > 0) {
425
				list.splice(0, 1);
426
			}
427
			return list;
428
		}
429
	},
430
	removeFirstX: function(count, returnNew = false){
431
		var list = this;
432
		
433
		// if fewer items than wanted, clear entire array
434
		if (list.length < count) {
435
			if (returnNew) {
436
				return [];
437
			}
438
			list.length = 0;
439
			return list;
440
		}
441
		
442
		// delete X items from start
443
		if (returnNew) {
444
			return list.slice(count);
445
		}else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
446
			list.splice(0, count);
447
			return list;
448
		}
449
	},
450
	removeLast: function(returnNew = false){
451
		var list = this;
452
		if (returnNew) {
453
			return list.slice(0, list.length - 1);
454
		}
455
		if (list.length > 0) {
456
			list.splice( - 1, 1);
457
		}
458
		return list;
459
	},
460
	removeLastX: function(count, returnNew = false){
461
		var list = this;
462
		
463
		// if fewer items than wanted, clear entire array
464
		if (list.length < count) {
465
			if (returnNew) {
466
				return [];
467
			}
468
			list.length = 0;
469
			return list;
470
		}
471
		
472
		// delete X items from end
473
		if (returnNew) {
474
			return list.slice(0, list.length - count);
475
		}else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
476
			list.splice( -count, count);
477
			return list;
478
		}
479
	},
480
	
481
	removeEdges: function(fromLeftEdge, fromRightEdge){
482
		var list = this;
483
		if ((list.length - fromLeftEdge - fromRightEdge) <= 0) {
484
			return [];
485
		}
486
		return list.slice(fromLeftEdge, list.length - fromRightEdge);
487
	},
488
	
489
	contains: function(value){
490
		var list = this;
491
		if (list.length == 1) {
1 ignored issue
show
Best Practice introduced by
Comparing list.length to 1 using the == operator is not safe. Consider using === instead.
Loading history...
492
			return list[0] == value;
493
		}
494
		return list.indexOf(value) > -1;
495
	},
496
	containsAny: function(values){
497
		var list = this;
498
		return IndexOfAny(list, values) > -1;
499
	},
500
	containsAll: function(values){
501
		var list = this;
502
		
503
		// exit if either null
504
		if (list == null || values == null || list.length === 0 || values.length === 0) {
2 ignored issues
show
Best Practice introduced by
Comparing values to null using the == operator is not safe. Consider using === instead.
Loading history...
Best Practice introduced by
Comparing list to null using the == operator is not safe. Consider using === instead.
Loading history...
505
			return false;
506
		}
507
		
508
		// check if all found
509
		for (var f = 0, fl = values.length;f<fl;f++){
510
			if (list.indexOf(values[f]) == -1) {
511
				return false;
512
			}
513
		}
514
		return true;
515
	},
516
	
517
	
518
	splitAt: function(slot, includeSlot = false, includeInFirst = false){
519
		var list = this;
520
		if (includeSlot) {
521
			if (includeInFirst) {
522
				return [list.slice(0, slot + 1), list.slice(slot + 1)];
523
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
524
				return [list.slice(0, slot), list.slice(slot)];
525
			}
526
		}
527
		return [list.slice(0, slot), list.slice(slot+1)];
528
	},
529
	splitAtEvery: function(val){
530
		var list = this;
531
		var splits = [];
532
		var lastSlot = 0;
533
		for (var a = 0, al = list.length;a<al;a++){
534
			if (list[a] == val && a > lastSlot) {
535
				splits.push(list.slice(lastSlot, a));
536
				lastSlot = a + 1;
537
			}
538
		}
539
		return splits;
540
	},
541
	
542
	moveToTop: function(slot, returnNew = false){
543
		var list = this;
544
545
		if (returnNew){
546
547
			// ALWAYS RETURNS NEW ARRAY
548
			
549
			// exit quickly if slot not in array
550
			var al = list.length;
551
			if (slot < 0 || slot >= al) {
552
				return list.concat();
553
			}
554
			
555
			// create new array with slot on top
556
			var newArr = [list[slot]];
557
			var n = 1;
558
			
559
			// add all other slots
560
			for (var a = 0;a<al;a++){
561
				if (a != slot) {
562
					newArr[n++] = list[a];
563
				}
564
			}
565
566
			return newArr;
567
568
		}else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
569
570
			// MODIFIES ARRAY IN PLACE
571
			
572
			// exit quickly if slot not in array
573
			var al = list.length;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable al already seems to be declared on line 550. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
574
			if (slot < 0 || slot >= al) {
575
				return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
576
			}
577
			
578
			// delete and re-add slot
579
			var val = list[slot];
580
			list.splice(slot, 1);
581
			list.unshift(val);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
582
		}
583
	},
584
	moveToBottom: function(slot, returnNew = false){
585
		var list = this;
586
587
		if (returnNew){
588
589
			// ALWAYS RETURNS NEW ARRAY
590
			
591
			// exit quickly if slot not in array
592
			var al = list.length;
593
			if (slot < 0 || slot >= al) {
594
				return list.concat();
595
			}
596
			
597
			// create new array with slot on top
598
			var newArr = [];
599
			var n = 0;
600
			
601
			// add all other slots
602
			for (var a = 0;a<al;a++){
603
				if (a != slot) {
604
					newArr[n++] = list[a];
605
				}
606
			}
607
			
608
			// add slot to bottom
609
			newArr[n++] = list[slot];
0 ignored issues
show
Unused Code introduced by
The assignment to variable n seems to be never used. Consider removing it.
Loading history...
610
			return newArr;
611
612
		}else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
613
614
			// MODIFIES ARRAY IN PLACE
615
			
616
			// exit quickly if slot not in array
617
			var al = list.length;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable al already seems to be declared on line 592. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
618
			if (slot < 0 || slot >= al) {
619
				return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
620
			}
621
			
622
			// delete and re-add slot
623
			var val = list[slot];
624
			list.splice(slot, 1);
625
			list.push(val);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
626
		}
627
	},
628
	moveUp: function(item){
629
		var list = this;
630
		
631
		// MODIFIES ARRAY IN PLACE
632
		
633
		// exit quickly if slot not in array, or already on top
634
		var slot = list.indexOf(item);
635
		if (slot <= 0) {
636
			return false;
637
		}
638
		
639
		// move one up
640
		Swap(list, slot, slot - 1);
641
		return true;
642
	},
643
	moveDown: function(item){
644
		var list = this;
645
		
646
		// MODIFIES ARRAY IN PLACE
647
		
648
		// exit quickly if slot not in array, or already at bottom
649
		var al = list.length;
650
		var slot = list.indexOf(item);
651
		if (slot < 0 || slot >= (al - 1)) {
652
			return false;
653
		}
654
		
655
		// move one down
656
		Swap(list, slot, slot + 1);
657
		return true;
658
	},
659
	moveSlotUp: function(slot){
660
		var list = this;
661
		
662
		// MODIFIES ARRAY IN PLACE
663
		
664
		// exit quickly if slot not in array, or already on top
665
		var al = list.length;
666
		if (slot <= 0 || slot >= al) {
667
			return false;
668
		}
669
		
670
		// move one up
671
		Swap(list, slot, slot - 1);
672
		return true;
673
	},
674
	moveSlotDown: function(slot){
675
		var list = this;
676
		
677
		// MODIFIES ARRAY IN PLACE
678
		
679
		// exit quickly if slot not in array, or already at bottom
680
		var al = list.length;
681
		if (slot < 0 || slot >= (al - 1)) {
682
			return false;
683
		}
684
		
685
		// move one down
686
		Swap(list, slot, slot + 1);
687
		return true;
688
	},
689
	/** Move an item from the given list, to the start/end of the target list */
690
	moveToArray: function(item, toList, evenIfExists = false, addToEnd = true){
691
		var list = this;
692
		
693
		// remove from source list
694
		RemoveOne(list, item);
695
		
696
		// add to target list
697
		if (evenIfExists || toList.indexOf(item) == -1) {
698
			if (addToEnd) {
699
				toList.push(item);
700
			}else{
701
				toList.unshift(item);
702
			}
703
			return true;
704
		}
705
		
706
		return false;
707
	},
708
	beginsWithArray: function(value){
709
		return this.startsWithArray(value);
710
	},
711
	startsWithArray: function(check){
712
		var list = this;
713
		
714
		// quickly test if length sufficient
715
		var clen = check.length;
716
		var mlen = list.length;
717
		if (mlen < clen) {
718
			return false;
719
		}
720
		
721
		// check if first slots match
722
		for (var b = 0;b<clen;b++){
723
			if (list[b] != check[b]) {
724
				return false;
725
			}
726
		}
727
		return true;
728
	},
729
	endsWithArray: function(check){
730
		var list = this;
731
		
732
		// quickly test if length sufficient
733
		var clen = check.length;
734
		var mlen = list.length;
735
		if (mlen < clen) {
736
			return false;
737
		}
738
		
739
		// check if last slots match
740
		var off = (mlen - clen);
741
		for (var b = 0;b<clen;b++){
742
			if (list[off + b] != check[b]) {
743
				return false;
744
			}
745
		}
746
		return true;
747
	},
748
	indexOfArray: function(containsArr){
749
		var list = this;
750
		
751
		// returns index of containing list in main array
752
		
753
		if (list.length < containsArr.length) {
754
			return -1;
755
		}
756
		
757
		var cl = containsArr.length;
758
		for (var a = 0, al = list.length - (cl - 1);a<al;a++){
759
			
760
			var allMatch = true;
761
			for (var c = 0;c<cl;c++){
762
				if (list[a+c] != containsArr[c]) {
763
					allMatch = false;
764
					break;
765
				}
766
			}
767
			
768
			if (allMatch) {
769
				return a;
770
			}
771
		}
772
		return -1;
773
	},
774
	
775
	beginsWith: function(value){
776
		return this.startsWith(value);
777
	},
778
	startsWith: function(value){
779
		var list = this;
780
		return list[0] == value;
781
	},
782
	endsWith: function(value){
783
		var list = this;
784
		return list[list.length - 1] == value;
785
	},
786
	
787
	next: function(obj, wrap = false){
788
		var list = this;
789
		if (list == null) {
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the == operator is not safe. Consider using === instead.
Loading history...
790
			return null;
791
		}
792
		var i = list.indexOf(obj);
793
		if (i > -1) {
794
			return (wrap && i >= (list.length - 1)) ? list[0] : list[i + 1];
795
		}
796
		return null;
797
	},
798
	prev: function(obj, wrap = false){
799
		var list = this;
800
		if (list == null) {
1 ignored issue
show
Best Practice introduced by
Comparing list to null using the == operator is not safe. Consider using === instead.
Loading history...
801
			return null;
802
		}
803
		var i = list.indexOf(obj);
804
		if (i > 0) {
805
			return wrap ? list[list.length - 1] : list[i - 1];
806
		}
807
		return null;
808
	},
809
	
810
	
811
	/** Returns the nearest existing slot value in the array. Returns `ifNoSlots` if the array is empty. */
812
	within: function(slot, ifNoSlots = null){
813
		var list = this;
814
		
815
		// return null if array empty
816
		var len = list.length;
817
		if (len == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
818
			return ifNoSlots;
819
		}
820
		
821
		// return first slot if index negative
822
		if (slot < 0) {
823
			return list[0];
824
		}
825
		
826
		// return last slot if index more than last slot
827
		if (slot >= len) {
828
			return list[len - 1];
829
		}
830
		
831
		// return given slot if within array
832
		return list[slot];
833
	},
834
	
835
	first: function(list){
836
		var list = this;
837
		var len = list.length;
838
		if (len == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
839
			return null;
840
		}
841
		return list[0];
842
	},
843
	firstExisting: function(slots, blankVal = null){
844
		var list = this;
845
		for (var s = 0, sl = slots.length;s<sl;s++){
846
			var val;
847
			if ((val = list[slots[s]]) != blankVal) {
848
				return val;
849
			}
850
		}
851
		return null;
852
	},
853
	last: function(list){
854
		var list = this;
855
		var len = list.length;
856
		if (len == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
857
			return null;
858
		}
859
		return list[len-1];
860
	},
861
	lastX: function(count){
862
		var list = this;
863
		var s = (0).max(list.length - count);
864
		return list.slice(s, list.length);
865
	},
866
	setFirst: function(value){
867
		var list = this;
868
		var len = list.length;
869
		if (len == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
870
			return;
871
		}
872
		list[0] = value;
873
	},
874
	setLast: function(value){
875
		var list = this;
876
		var len = list.length;
877
		if (len == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
878
			return;
879
		}
880
		list[len-1] = value;
881
	},
882
	
883
	random: function(list){
884
		var list = this;
885
		
886
		// return null if array empty
887
		if (list.length === 0) {
888
			return null;
889
		}
890
		
891
		// return random slot within array
892
		return list[parseInt(Math.random() * 1000000) % list.length];
893
	},
894
895
	pick: function(IDs, sameSlots = false, fastAndUnsafe = false, out = null, evenIfNull = false){
896
		var list = this;
897
		if (out == null){
1 ignored issue
show
Best Practice introduced by
Comparing out to null using the == operator is not safe. Consider using === instead.
Loading history...
898
			out = [];
899
		}
900
		
901
		if (IDs){
902
			if (fastAndUnsafe) {
903
				
904
				for (var i = 0, il = IDs.length;i<il;i++){
905
					var id = IDs[i];
906
					var val = list[id];
907
					if (sameSlots) {
908
						out[id] = val;
909
					}else{
910
						out.push(val);
911
					}
912
				}
913
				
914
			}else{
915
				
916
				for (var i = 0, il = IDs.length;i<il;i++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 904. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
Comprehensibility Naming Best Practice introduced by
The variable il already seems to be declared on line 904. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
917
					id = IDs[i];
918
					if (id > -1){
919
						val = list[id];
920
						if (val != null || evenIfNull) {
1 ignored issue
show
Best Practice introduced by
Comparing val to null using the != operator is not safe. Consider using !== instead.
Loading history...
921
							if (sameSlots) {
922
								out[id] = val;
923
							}else{
924
								out.push(val);
925
							}
926
						}
927
					}
928
				}
929
				
930
			}
931
		}
932
		
933
		return out;
934
	},
935
936
	/** Get the data of `list`, by searching `indexID` in `indexArr`, or return `defaultVal` if not found */
937
	getByMatchingArray: function(indexArr, indexID, defaultVal = null){
938
		var list = this;
939
		var slot = indexArr.indexOf(indexID);
940
		return slot == -1 ? defaultVal : list[slot];
941
	},
942
	/** Set the data of `list`, by searching `indexID` in `indexArr` */
943
	setByMatchingArray: function(indexArr, indexID, data){
944
		var list = this;
945
		var slot = indexArr.indexOf(indexID);
946
		if (slot == -1) {
947
			return false;
948
		}
949
		list[slot] = data;
950
		return true;
951
	},
952
	
953
	page: function(page, pageLength, invisibleRows = null){
954
		var list = this;
955
		
956
		// ensure page no. in limits
957
		var lastPage = Math.ceil(list.length / pageLength);
958
		page = page.limitTo(0, lastPage - 1);
959
		
960
		// get first/last row in page
961
		var pageStart = page*pageLength;/// 0-based - first row in page
962
		var pageEnd = (pageStart + pageLength) - 1;/// 0-based - last row in page
963
		
964
		// get on-page rows
965
		var visibleRows = list.getRange(pageStart, pageLength);
966
		
967
		// get off-page rows
968
		if (invisibleRows) {
969
			invisibleRows.addRange(list, 0, pageStart - 1);
970
			invisibleRows.addRange(list, pageEnd + 1, list.length - 1);
971
		}
972
		
973
		return visibleRows;
974
	},
975
	
976
	trim: function(returnNew = false, trimVal = null){
977
		var list = this;
978
		var first = IndexOf(list, trimVal, true);
979
		if (first == -1) {
980
			if (returnNew) {
981
				return [];
982
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
983
				list.length = 0;
984
			}
985
		}else{
986
			var last = list.lastIndexOf(trimVal, true);
987
			if (returnNew) {
988
				return GetManySE(list, first, last);
989
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
990
				
991
				if (first != -1 && first != 0){
1 ignored issue
show
Best Practice introduced by
Comparing first to 0 using the != operator is not safe. Consider using !== instead.
Loading history...
992
					DeleteManySE(list, 0, first-1);
993
				}
994
				if (last != -1){
995
					list.length = last - first + 1; 
996
				}
997
			}
998
		}
999
		return list;
1000
	},
1001
1002
	trimLeft: function(returnNew = false, trimVal = null){
1003
		var list = this;
1004
		var first = IndexOf(list, trimVal, true);
1005
		if (first == -1) {
1006
			if (returnNew) {
1007
				return [];
1008
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1009
				list.length = 0;
1010
			}
1011
		}else{
1012
			if (returnNew) {
1013
				return GetAfter(list, first);
1014
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1015
				if (first != -1 && first != 0){
1 ignored issue
show
Best Practice introduced by
Comparing first to 0 using the != operator is not safe. Consider using !== instead.
Loading history...
1016
					DeleteManySE(list, 0, first-1);
1017
				}
1018
			}
1019
		}
1020
		return list;
1021
	},
1022
	trimRight: function(returnNew = false, trimVal = null){
1023
		var list = this;
1024
		var last = IndexOf(list, trimVal, true);
1025
		if (last == -1) {
1026
			if (returnNew) {
1027
				return [];
1028
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1029
				list.length = 0;
1030
			}
1031
		}else{
1032
			if (returnNew) {
1033
				return GetBefore(list, last);
1034
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1035
				list.length = last + 1;
1036
			}
1037
		}
1038
		return list;
1039
	},
1040
	
1041
	transpose: function() {
1042
		var arr = this;
1043
		var transposed = [];
1044
		
1045
		for (var r = 0; r < arr.length; r++) {
1046
			for (var c = 0; c < arr[r].length; c++) {
1047
				if (transposed[c] == null) {
1 ignored issue
show
Best Practice introduced by
Comparing transposed.c to null using the == operator is not safe. Consider using === instead.
Loading history...
1048
					transposed[c] = [];
1049
				}
1050
				transposed[c][r] = arr[r][c];
1051
			}
1052
		}
1053
		
1054
		return transposed;
1055
	},
1056
1057
	
1058
	none:null
1059
};
1060
1061
// register funcs
1062
UB.registerFuncs(Array.prototype, arrayFuncs);
1063